package org.sundatagroup.aurora.core.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.sundatagroup.aurora.core.dao.ProjectDao;
import org.sundatagroup.aurora.core.entity.model.ProjectModel;
import org.sundatagroup.aurora.core.entity.particle.Particle;
import org.sundatagroup.aurora.core.entity.pojo.Module;
import org.sundatagroup.aurora.core.entity.pojo.Project;
import org.sundatagroup.aurora.core.service.querier.IQuerier;

import com.google.gson.JsonElement;

/**
 * <p>封装了 {@link Project} 普通 CRUD 操作, 按增删改查排序
 * </p>
 * 
 * @version 0.2.0
 * <li>补充通用查询接口
 * <li>利用 {@link Particle} 合并配置项
 * </li>
 * 
 * @author CharlesChen
 * @author Zdream
 * @date 2018-05-30
 * @since 0.1
 */
@Service
public class ProjectService implements IQuerier {
	@Autowired
	ProjectDao projectDao;
	
	@Autowired
	ModuleService moduleService;

	@Autowired
	ParticleService particleSv;

	/**
	 * 保存一个{@link Project}
	 * @param p 设值完毕的Project
	 * @throws IllegalArgumentException Project参数错误
	 * @deprecated
	 *   暂时不提供添加服务
	 */
	@Deprecated
	public void add(Project p) {
		if (p == null || !p.isValid()) {
		    throw new IllegalArgumentException("Project参数错误，请修改！");
		}
		ProjectModel pm = p.toModel();
		projectDao.insert(pm);
		//检查传入Project的Modules是否为新的Module，如为新的Module则需入库
		List<Module> ms = p.getModules();
		List<Module> moduleList = moduleService.queryAll();
		Map<Integer, Module> integerModuleMap = moduleService.list2map(moduleList);
		for (Module m : ms) {
		    if (!integerModuleMap.containsKey(m.getMid())) {
		        moduleService.add(m);
		    }
		}
	}

	/**
	 * 查操作：根据 pid 查询{@link Project}
	 * @param pid
	 * @throws IllegalArgumentException
	 *   参数 Project 中的 mid 不合法
	 * @return
	 */
	public Project queryByPid(int pid) {
		ProjectModel pm = projectDao.findByPid(pid);
		if (pm == null) {
			return null;
		}
		Project p = Project.fromModel(pm);
		//为Project填入Modules
		List<Module> modules = midsToModules(pm.getModules());
		p.setModules(modules);
		
		// 装配 particle 部分 
		// since 0.2.0
		assemble(p);

		return p;
	}
	
	/**
	 * 返回所有的 {@link Project}
	 * @return project 集合
	 */
	public List<Project> queryAll() {
		Project p;
		List<Module> modules;
		List<ProjectModel> projectModels = projectDao.findAll();
		if (projectModels == null) {
			return null;
		}
		List<Project> projects = new ArrayList<>(projectModels.size());
		for (ProjectModel pm : projectModels) {
		    p = Project.fromModel(pm);
		    modules = midsToModules(pm.getModules());
		    p.setModules(modules);
		    projects.add(p);
		}

		return projects;
	}

	/**
	 * List<mid>转换为List<Module>
	 * @param mids
	 * @return
	 */
	public List<Module> midsToModules(List<Integer> mids) {
		Module m;
		List<Module> modules = new ArrayList<>(mids.size());
	    for (Integer mid : mids) {
	        if ((m = moduleService.queryByMid(mid)) == null) {
				throw new IllegalArgumentException("输入Project的mid有误，请检查！");
	        } else {
	        	modules.add(m);
			}
	    }

	    return modules;
	}

	/**
	 * 用分页的方式进行{@link Project}的查询
	 * @param start 起始索引
	 * @param size 数据条目数量
	 * @return
	 */
	public List<Project> queryByPage(int start, int size) {
		List<ProjectModel> projectModels = projectDao.findByPage(start, size);
		List<Project> projectList = new ArrayList<>(projectModels.size());

		for (ProjectModel projectModel : projectModels) {
		    projectList.add(Project.fromModel(projectModel));
		}

		return projectList;
	}

	/**
	 * 计算 {@link Project} 数量
	 * @return
	 */
	public int countProjects() {
		return projectDao.count();
	}
	
	/* **********
	 * 通用查询 *
	 ********** */
	/*
	 * 通用查询服务
	 * since 0.2.0
	 */

	@Override
	public String[] types() {
		return new String[] {"/query/project"};
	}

	/**
	 * 允许 <code>"/query/project"</code> 查询数据, 按 id 进行查询
	 * @since 0.2.0
	 */
	@Override
	public JsonElement query(String type, JsonElement key) {
		if (key.isJsonObject()) {
			Project p = this.queryByPid(key.getAsJsonObject().get("id").getAsInt());
			if (p != null) {
				return p.toJson();
			}
		}
		
		return null;
	}
	
	/* **********
	 * 配置装载 *
	 ********** */
	/*
	 * 配置项从 Project 中分离开之后, 单独新建了表项 Particle.
	 * 在 Project 形成时, 就需要将配置重新读入并装载.
	 * since 0.2.0
	 */
	
	/**
	 * 为 <code>p</code> 装配配置项, 补全 p.particles 和 p.options 部分.
	 * @param p
	 */
	private void assemble(Project p) {
		particleSv.assemble(p);
	}
}
